package generic;

import java.util.ArrayList;
import java.util.List;

/**
 * @author ChangLiang
 * @date 2021/2/1
 */
public class GenericsAndCovariance {

    public static void main(String[] args) {
        // Wildcards allow covariance:
        List<? extends Fruit> flist = new ArrayList<Apple>();

        /**
         * 这实际上并不意味着这个List将持有任何类型的Fruit。
         * 通配符引用的是明确的类型，因此它意味着“某种flist引用没有指定的具体类型”
         * 因此这个被赋值的List必须持有诸如Fruit或Apple这样的某种指定类型，
         * 但是为了向上转型为flist，这个类型是什么并没有人关心。
         *
         * 如果唯一的限制是这个List要持有某种具体的Fruit或Fruit的子类型，但是你实际上并不关
         * 心它是什么，那么你能用这样的List做什么呢？
         * 如果不知道List持有什么类型，那么你怎样才能安全地向其中添加对象呢？
         *
         * 现在你甚至不能向刚刚声明过将持有Apple对象的List中放置－个Apple对象了。
         * 是的，但是编译器并不知道这一点。List<? extends Fruit>可以合法地指向一个List<Orange>。
         *
         * 一旦执行这种类型的向上转型，你就将丢失掉向其中传递任何对象的能力，甚至是传递Object也不行。
         *
         */
        // Compile Error: can't add any type of object:
        // flist.add(new Apple());
        // flist.add(new Fruit());
        // flist.add(new Object());
        flist.add(null); // Legal but uninteresting
        // We know that it returns at least Fruit:
        /**
         * 另一方面，如果你调用一个返回Fruit的方法，则是安全的， 因为你知道在这个List中的任何
         * 对象至少具有Fruit类型，因此编译器将允许这么傲。
         */
        Fruit f = flist.get(0);
    }
}
